package com.gcb.framework.aspectj;

import com.gcb.common.annotation.SmsRateLimiter;
import com.gcb.common.core.redis.RedisCache;
import com.gcb.common.utils.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.time.LocalDate;
import java.util.concurrent.TimeUnit;

/**
 * 短信限流处理
 *
 * @author ych
 */
@Aspect
@Component
public class RateSmsAspect {
    @Autowired
    private RedisCache redisCache;

    /**
     * 短信限流
     *
     * @param point          切点
     * @param smsRateLimiter 短信限流注解
     * @author ych
     */
    @Before("@annotation(smsRateLimiter)")
    public void doBefore(JoinPoint point, SmsRateLimiter smsRateLimiter) {
        //获得短信限流key
        String key = smsRateLimiter.key();
        //获取短信限流次数
        int count = smsRateLimiter.count();
        //获取短信限流时间 单位秒 默认一天
        int time = smsRateLimiter.time();
        //获取手机号码
        Object[] args = point.getArgs();
        // 假设mobile是第一个参数
        if (args.length > 0 && args[0] instanceof String) {
            String mobile = (String) args[0];
            // 在这里可以添加你的限流逻辑
            if (!canSendSms(key, mobile, count, time)) {
                throw new RuntimeException("短信发送过于频繁，请明天再试");
            }
        } else {
            throw new RuntimeException("手机号不正确");
        }
    }

    /**
     * 判断是否可以发送短信
     *
     * @param key       redis中的key
     * @param mobile    手机号
     * @param rateCount 限流次数
     * @param rateTime  限流时间
     * @author ych
     */
    public boolean canSendSms(String key, String mobile, int rateCount, int rateTime) {
        // 使用日期作为键的一部分，确保每天一个键
        String smsKey = key + mobile + ":" + LocalDate.now();
        // 获取当前发送的短信数
        String value = redisCache.getCacheObject(smsKey);
        // 如果当天没有设置限流key，则设置为1
        if (StringUtils.isBlank(value)) {
            // 增加发送的短信数，并设置过期时间为一天（86400秒）
            redisCache.setCacheObject(smsKey, "1", rateTime, TimeUnit.SECONDS);
            //用户当天是第一次发送注册短信
            return true;
        }
        int count = 0;
        //判断redis中有没有key
        if (StringUtils.isNotEmpty(value)) {
            count = Integer.parseInt(value);
        }
        // 如果发送了rateCount条或更多，则返回false
        // 默认20条限流
        if (count >= rateCount) {
            return false;
        }
        // 否则，将发送的短信数加1，并设置过期时间为一天（86400秒）
        redisCache.setCacheObject(smsKey, String.valueOf(count + 1), rateTime, TimeUnit.SECONDS);
        return true; //可以继续发送短信
    }
}
